package cn.edu.nju.ws.sview.crawler;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;

import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.RDFReader;


/**
 * RDF文档解析
 * @author Gong Saisai
 *
 */
public class Parser {
    private static Parser INSTANCE = null;
    private Parser(){
    	
    }
    
    public synchronized static Parser getInstance(){
    	if(INSTANCE==null)
    		INSTANCE = new Parser();
    	return INSTANCE;
    }
    
    
    /**
     * 解析下载的文档的内容
     * @param rdfDocumentURI 解析的RDF文档URI
     * @param serializationFormat 文档类型
     * @param content 文档内容的字节流
     * @return OntModel 可能为NULL
     */
    public OntModel parse(String rdfDocumentURI, String serializationFormat,
			byte[] content){
    	OntModel ontModel  = null;
    	ByteArrayInputStream  inputStream = new ByteArrayInputStream(content);
    	//获得文档可能存在的xml:base，如果不存在则base是文档URI本身
    	String base = null;
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false) ;
			factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
			SAXParser saxparser  = factory.newSAXParser();
			XMLBaseFinder baseFinder = new XMLBaseFinder();
			saxparser.parse(inputStream,baseFinder);
			base = baseFinder.getXmlBase();
		} catch (SAXNotRecognizedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (SAXNotSupportedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (ParserConfigurationException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			base = null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			base = null;
		}
		//流重定位到开始位置
        inputStream.reset();
        if(base ==null)
        	base = rdfDocumentURI;
        
    	ontModel = ModelFactory.createOntologyModel(OntModelSpec.RDFS_MEM) ;
    	
    	//去除不必要的NS声明
		Map<String, String> nsPrefixMapTemp = ontModel.getNsPrefixMap();
		for (String prefix : nsPrefixMapTemp.keySet()) {
			ontModel.removeNsPrefix(prefix);
		}
		nsPrefixMapTemp.clear();
		
    	RDFReader reader  = null;
    	if(serializationFormat.equals("RDF/XML")){
    		reader = ontModel.getReader("RDF/XML");
    		reader.setProperty("http://apache.org/xml/features/nonvalidating/load-external-dtd", new Boolean(false)) ;
    		reader.setProperty("http://xml.org/sax/features/external-parameter-entities", new Boolean(false));
    	}else if(serializationFormat.equals("RDFa")){
    	    try {
				Class.forName("net.rootdev.javardfa.jena.RDFaReader") ;
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			reader = ontModel.getReader("XHTML");
    	}else{
    		throw new IllegalArgumentException(serializationFormat
					+ "不是支持的RDF文档序列化格式");
    	}
    	try{
    		reader.read(ontModel, inputStream, base) ;
    	}catch(Exception e){
    		ontModel = null;
    		e.printStackTrace();
    	}
    	
    	return ontModel;
    }
    
}
